import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/*
 怎么避免sql注入？
 sql注入的根本原因是，先进行了字符串的拼接，然后在进行的编译。

  java.sql.Statement接口的特点，先进行字符串的拼接。然后再进行sql语句的编译。
  优点：使用Statement可以进行sql语句的拼接。
  缺点：因为拼接的存在，导致可能给不法分子机会。

  java.sql.PreparedStatement接口的特点，先进行sql语句的编译，然后在进行sql语句的传值。
   优点：避免sql注入。
   缺点:没有办法进行sql语句的拼接，只能给sql语句传值。
   PreparedStatement预编译的数据库操作对象
*/

public class JDBCTest03 {
    public static void main(String[] args) {
        //初始化一个界面，可以让用户输入用户名和密码
        Map<String,String>userLoginInfo=initUI();
        //连接数据库验证用户和密码是否正确
        boolean ok=checkNameAndPwd(userLoginInfo.get("loginName"),userLoginInfo.get("loginPwd"));
        System.out.println(ok?"登陆成功":"登陆失败");

    }

    private static boolean checkNameAndPwd(String loginName, String loginPwd) {
        boolean ok=false;//默认登录是失败的，
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;

        // 1、注册驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2、获取连接
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc", "root", "root");
            // 3、获取预编译的数据库操作对象
            //一个问号是一个占位符，一个占位符只能接收一个值/数据
            String sql = "select * from t_user where login_name=? and login_pwd=?";
            stmt=conn.prepareStatement(sql);//此时会发送sql给DBMS，进行sql语句的编译
            //给占位符?传值
            //怎么解决sql注入的？即使用户信息中有sql关键字，但是不参加编译就没事。
            //stmt.setInt(1,100);//这样必须是填数字，↓下面那个必须填字符串。
            stmt.setString(1,loginName);//给第一个占位符传值
            stmt.setString(2,loginPwd);//给第二个占位符传值
            // 4、执行sql语句
            rs = stmt.executeQuery();//这个方法不需要将sql语句传递进去，不能是这样：rs = stmt.executeQuery(sql);因为上面已经把sql传过去了。
            if(rs.next()){//此条件如果成立，表示登录成功
                ok=true;
            }
            // 5、处理结果集
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 6、释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn!= null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

        return ok;
    }


    private static Map<String, String> initUI(){
        System.out.println("欢迎使用该系统，请输入用户名和密码进行身份认证");
        Scanner s=new Scanner(System.in);
        System.out.println("用户名：");
        String loginName=s.nextLine();
        System.out.println("密码：");
        String loginPwd=s.nextLine();
        //将用户名和密码放在map集合中
        Map<String,String> useLoginInfo=new HashMap<>();
        useLoginInfo.put("loginName",loginName);
        useLoginInfo.put("loginPwd",loginPwd);
        //返回map
        return useLoginInfo;

    }


}

